/*
 *  Copyright 2004 Blandware (http://www.blandware.com)
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.blandware.atleap.webapp.action.core.search;

import com.blandware.atleap.common.Constants;
import com.blandware.atleap.common.util.PartialCollection;
import com.blandware.atleap.model.core.User;
import com.blandware.atleap.search.SearchManager;
import com.blandware.atleap.service.core.UserManager;
import com.blandware.atleap.webapp.action.core.grid.BaseGridAction;
import com.blandware.atleap.webapp.form.core.SearchForm;
import com.blandware.atleap.webapp.util.core.GlobalProperties;
import com.blandware.atleap.webapp.util.core.WebappConstants;
import com.blandware.atleap.webapp.util.core.WebappUtil;
import org.apache.lucene.queryParser.ParseException;
import org.apache.struts.Globals;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Locale;

/**
 * <p>Returns page with search results (hits)
 * </p>
 * <p><a href="SearchAction.java.html"><i>View Source</i></a></p>
 * <p/>
 *
 * @author Andrey Grebnev <a href="mailto:andrey.grebnev@blandware.com">&lt;andrey.grebnev@blandware.com&gt;</a>
 * @version $Revision: 1.13 $ $Date: 2005/08/24 10:22:29 $
 * @struts.action path="/core/search/search"
 * validate="true"
 * input="inputForward"
 * name="searchForm"
 * @struts.action-forward name="searchResults"
 * path=".core.search.results"
 * @struts.action-forward name="inputForward"
 * path="/core/search/callSearch.do"
 */
public final class SearchAction extends BaseGridAction {

	/**
	 * @param mapping  The ActionMapping used to select this instance
	 * @param form     The optional ActionForm bean for this request (if any)
	 * @param request  The HTTP request we are proceeding
	 * @param response The HTTP response we are creating
	 * @return an ActionForward instance describing where and how
	 *         control should be forwarded, or null if response
	 *         has already been completed
	 */
	public ActionForward execute(ActionMapping mapping, ActionForm form,
	                             HttpServletRequest request, HttpServletResponse response) throws Exception {

		SearchForm searchForm = (SearchForm) form;

		//set page number
		int pageNumber = 1;
		if ( request.getParameter("pageNumber") != null ) {
			pageNumber = Integer.parseInt(request.getParameter("pageNumber"));
		} else {
			//if pageNubmer is not specified it means that this the first query
			request.getSession().removeAttribute(WebappConstants.SEARCH_HITS_COLLECTION_KEY);
			request.getSession().removeAttribute(WebappConstants.SEARCH_QUERY_KEY);
		}

		//set language
        boolean allLanguages = false;
		String language = searchForm.getSearchLanguage();
        if (language == null || language.trim().length() == 0) {
            allLanguages = true;
            if (request.getSession().getAttribute(Globals.LOCALE_KEY) != null) {
                language = ((Locale) request.getSession().getAttribute(Globals.LOCALE_KEY)).getLanguage();
            }
        }
		if ( language == null ) {
			language = Locale.getDefault().getLanguage();
		}

		//set time period in days
		int days = 0;
		if ( searchForm.getTimePeriod() != null ) {
			days = Integer.parseInt(searchForm.getTimePeriod());
		}

		//set query criteria
		List hits = null;
		String criteria = searchForm.getQuery();
		if ( criteria == null || criteria.trim().length() == 0 ) {
			//get from session
			hits = (List) request.getSession().getAttribute(WebappConstants.SEARCH_HITS_COLLECTION_KEY);
			if ( hits != null ) {
				criteria = (String) request.getSession().getAttribute(WebappConstants.SEARCH_QUERY_KEY);
			} else {
				criteria = "";
			}
		}

		//get comma separated roles string of current user
		String roles = "";
		User user = (User) request.getSession().getAttribute(Constants.USER_KEY);
		if ( user != null ) {
			UserManager userManager = (UserManager) getBean(Constants.USER_MANAGER_BEAN);
			user = userManager.retrieveUser(user.getName());
			if ( user != null ) {
				roles = WebappUtil.rolesToString(user.getRoles());
			}
		}

		int pageSize = GlobalProperties.getInstance(servlet.getServletContext()).getInteger(WebappConstants.GRID_PAGE_SIZE, 10).intValue();
		int offset = (pageNumber - 1) * pageSize;

		if ( log.isDebugEnabled() ) {
			log.debug("Begin to search with following criteria: '" + criteria + "' and language: " + language);
		}

		SearchManager searchManager = SearchManager.getInstance(request.getSession().getServletContext());
		try {
			hits = searchManager.search(hits, criteria, language, allLanguages, days, roles, offset, pageSize, request);
			request.getSession().setAttribute(WebappConstants.SEARCH_HITS_COLLECTION_KEY, hits);
			request.getSession().setAttribute(WebappConstants.SEARCH_QUERY_KEY, criteria);
		} catch ( ParseException ex ) {
			ActionMessages errors = new ActionMessages();
			errors.add("searchQueryInvalid", new ActionMessage("core.search.errors.queryInvalid", ex.getMessage()));
			saveToken(request);
			return mapping.getInputForward();
		}

		int limit = (offset + pageSize) > hits.size() ? hits.size() : (offset + pageSize);
		List pagedHits = hits.subList(offset, limit);
		request.setAttribute(WebappConstants.HIT_COLLECTION_KEY, new PartialCollection(pagedHits, hits.size()));

		return mapping.findForward("searchResults");
	}


}